/*
 * Copyright (c) 2000-2017 wanglei. All rights reserved.
 * TeamDev PROPRIETARY and CONFIDENTIAL.
 * Use is subject to license terms.
 */

package com.xhb.ui;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.navigation.event.LoadFinished;
import com.teamdev.jxbrowser.navigation.event.LoadStarted;
import com.teamdev.jxbrowser.navigation.event.NavigationStarted;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import com.xhb.EasyBrowserApplication;
import com.xhb.biz.constant.UserConfigConstant;
import com.xhb.biz.controller.ViewSourceController;
import com.xhb.biz.po.CollectUrlPO;
import com.xhb.biz.po.ConfigPO;
import com.xhb.biz.service.CollectUrlService;
import com.xhb.biz.service.ConfigService;
import com.xhb.biz.service.HistoryService;
import com.xhb.ui.collect.CollectBar;
import com.xhb.ui.collect.UpdateCollectUrlDialog;
import com.xhb.ui.component.RoundJtextField;
import com.xhb.ui.proxy.ProxyManager;
import com.xhb.ui.resources.Resources;
import org.noear.solon.Solon;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
import java.awt.*;
import java.awt.event.*;

/**
 * 包括网址栏，前进后退刷新等按钮以及右键菜单
 *
 * @author wanglei.
 */
public class ToolBar extends JPanel {
    private static final String RUN_JAVASCRIPT = "Run JavaScript...";
    private static final String CLOSE_JAVASCRIPT = "Close JavaScript Console";
    private static final String DEFAULT_URL = "about:blank";

    private JButton backwardButton;
    private JButton forwardButton;
    private JButton refreshButton;
    private JButton stopButton;
    private JMenuItem consoleMenuItem;

    private final JTextField addressBar;
    private final BrowserView browserView;

    private final ProxyManager proxyManager;

    private final CollectBar collectBar;

    private JPanel jPanel;

    private ActionButton button;

    private ActionButton loginButton;

    public ToolBar(BrowserView browserView) {
        this.browserView = browserView;
        proxyManager = new ProxyManager();
        addressBar = createAddressBar();
        setLayout(new BorderLayout());
        Border border = new MatteBorder(0, 0, 1, 0, Color.LIGHT_GRAY);
        setBorder(border);
        jPanel = new JPanel();
        jPanel.setLayout(new GridBagLayout());
        jPanel.add(createActionsPane(), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
                GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        jPanel.add(addressBar, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4, 0, 4, 5), 0, 0));
//        jPanel.add(createCollectMenuButton(), new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
//                GridBagConstraints.LINE_END, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 0, 5), 0, 0));
//        jPanel.add(createLoginMenuButton(), new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
//                GridBagConstraints.LINE_END, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 5), 0, 0));
        jPanel.add(createLoginMenuButton(browserView), new GridBagConstraints(4, 0, 1, 1, 0.0, 0.0,
                GridBagConstraints.LINE_END, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 0, 5), 0, 0));
        jPanel.setBackground(Color.WHITE);
        add(jPanel, BorderLayout.NORTH);
        collectBar = new CollectBar();
        add(collectBar, BorderLayout.CENTER);
        setBackground(Color.WHITE);
    }

    public void setUrl(String url) {
        addressBar.setText(url);
    }

    public void didJSConsoleClose() {
        consoleMenuItem.setText(RUN_JAVASCRIPT);
    }

    private JPanel createActionsPane() {
        backwardButton = createBackwardButton(browserView.getBrowser());
        forwardButton = createForwardButton(browserView.getBrowser());
        refreshButton = createRefreshButton(browserView.getBrowser());
        stopButton = createStopButton(browserView.getBrowser());
        JPanel actionsPanel = new JPanel();
        actionsPanel.add(backwardButton);
        actionsPanel.add(forwardButton);
        actionsPanel.add(refreshButton);
        //注释掉停止按钮，很多浏览器都不带这个功能了
        /* actionsPanel.add(stopButton);*/
        actionsPanel.setBackground(Color.WHITE);
        return actionsPanel;
    }

    private JTextField createAddressBar() {
        final JTextField address = new RoundJtextField(DEFAULT_URL, browserView);
        address.setBackground(new Color(231, 234, 237));
        browserView.getBrowser().navigation().on(NavigationStarted.class, event -> {
            proxyManager.autoProxy(event.url(), browserView);
           // changeCollectIcon();
        });

        browserView.getBrowser().navigation().on(LoadStarted.class, event -> {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    refreshButton.setEnabled(false);
                    stopButton.setEnabled(true);
                }
            });
        });
        browserView.getBrowser().navigation().on(LoadFinished.class, event -> {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    forwardButton.setEnabled(event.navigation().canGoForward());
                    backwardButton.setEnabled(event.navigation().canGoBack());
                    refreshButton.setEnabled(true);
                    stopButton.setEnabled(false);
                    address.setText(event.navigation().browser().url());
                    //历史记录
                    Solon.context().getBeanAsync(HistoryService.class, bean -> {
                        bean.insertAsync(event);
                    });
                }
            });
        });
        return address;
    }

    private static JButton createBackwardButton(final Browser browser) {
        return createButton("Back", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.navigation().goBack();
            }
        });
    }

    private static JButton createForwardButton(final Browser browser) {
        return createButton("Forward", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.navigation().goForward();
            }
        });
    }

    private static JButton createRefreshButton(final Browser browser) {
        return createButton("Refresh", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.navigation().reload();
            }
        });
    }

    private static JButton createStopButton(final Browser browser) {
        return createButton("Stop", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                browser.navigation().stop();
            }
        });
    }

    private static JButton createButton(String caption, Action action) {
        ActionButton button = new ActionButton(caption, action);
        String imageName = caption.toLowerCase();
        button.setIcon(Resources.getIcon(imageName + ".png"));
        button.setRolloverIcon(Resources.getIcon(imageName + "-selected.png"));
        return button;
    }

    private JComponent createCollectMenuButton() {
        button = new ActionButton("Preferences", null);
        button.setIcon(Resources.getIcon("collect.png"));
        button.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
//                CollectUrlPO urlPO = changeCollectIcon();
//                button.setIcon(Resources.getIcon("collect_success.png"));
//                UpdateCollectUrlDialog updateCollectUrlDialog = new UpdateCollectUrlDialog(urlPO, collectBar, true);
//                updateCollectUrlDialog.setModal(true);
//                updateCollectUrlDialog.setVisible(true);
//                changeCollectIcon();
            }
        });
        return button;
    }

    private JComponent createLoginMenuButton(BrowserView browserView) {
        loginButton = new ActionButton("Preferences", null);
        ConfigPO configPo = Solon.context().getBean(ConfigService.class).selectUserConfigByKey(UserConfigConstant.USER_TOKEN_KEY);
        String iconName = null == configPo ? "logout.png" : "login.png";
        loginButton.setIcon(Resources.getIcon(iconName));
        loginButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                LoginLogoutFrame loginLogoutFrame = new LoginLogoutFrame(loginButton,browserView);
                loginLogoutFrame.setVisible(true);
            }
        });
        return loginButton;
    }

    public CollectUrlPO changeCollectIcon() {
        String url = browserView.getBrowser().url();
        CollectUrlPO urlPO = null;
        CollectUrlService bean = Solon.context().getBean(CollectUrlService.class);
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.likeLeft("url", url.replace("http://", "").replace("https://", ""));
        queryWrapper.last("limit 1");
        urlPO = bean.getOne(queryWrapper);
        if (null == urlPO) {
            urlPO = new CollectUrlPO();
            urlPO.setUrl(url);
            urlPO.setName(browserView.getBrowser().title());
//            button.setIcon(Resources.getIcon("collect.png"));
        } else {
//            button.setIcon(Resources.getIcon("collect_success.png"));
        }
        return urlPO;
    }


    private JComponent createMenuButton() {
        final JPopupMenu popupMenu = new JPopupMenu();
        popupMenu.add(createConsoleMenuItem());
        popupMenu.add(createPopupsMenuItem());
        popupMenu.add(createUploadFileMenuItem());
        popupMenu.add(createDownloadFileMenuItem());
        popupMenu.add(createJavaScriptDialogsMenuItem());
        popupMenu.add(createPDFViewerMenuItem());
        popupMenu.add(createEchartsMenuItem());
        popupMenu.add(createHTML5VideoMenuItem());
        popupMenu.add(createZoomInMenuItem());
        popupMenu.add(createZoomOutMenuItem());
        popupMenu.add(createActualSizeMenuItem());
        popupMenu.add(createPreferencesSubMenu());
        popupMenu.addSeparator();
        popupMenu.add(createAboutMenuItem());
        popupMenu.add(createLoginMenuItem());

        final ActionButton button = new ActionButton("Preferences", null);
        button.setIcon(Resources.getIcon("gear.png"));
        button.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
                    popupMenu.show(e.getComponent(), 0, button.getHeight());
                } else {
                    popupMenu.setVisible(false);
                }
            }
        });
        return button;
    }


    private Component createPreferencesSubMenu() {
        JMenu menu = new JMenu("首选项");
        menu.add(createCheckBoxMenuItem("启用JS", browserView.getBrowser().settings().isJavaScriptEnabled(), new CheckBoxMenuItemCallback() {
            public void call(boolean selected) {
                if (selected) {
                    browserView.getBrowser().settings().enableJavaScript();
                } else {
                    browserView.getBrowser().settings().disableJavaScript();
                }
                browserView.getBrowser().navigation().reloadIgnoringCache();
            }
        }));
        menu.add(createCheckBoxMenuItem("加载图片", browserView.getBrowser().settings().isImagesEnabled(), new CheckBoxMenuItemCallback() {
            public void call(boolean selected) {
                if (selected) {
                    browserView.getBrowser().settings().enableImages();
                } else {
                    browserView.getBrowser().settings().disableImages();
                }
                browserView.getBrowser().navigation().reloadIgnoringCache();
            }
        }));
        menu.add(createCheckBoxMenuItem("插件支持", browserView.getBrowser().settings().isPluginsEnabled(), new CheckBoxMenuItemCallback() {
            public void call(boolean selected) {
                if (selected) {
                    browserView.getBrowser().settings().enablePlugins();
                } else {
                    browserView.getBrowser().settings().disablePlugins();
                }
                browserView.getBrowser().navigation().reloadIgnoringCache();
            }
        }));
        return menu;
    }

    private static JCheckBoxMenuItem createCheckBoxMenuItem(String title, boolean selected, final CheckBoxMenuItemCallback action) {
        final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(title, selected);
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                action.call(menuItem.isSelected());
            }
        });
        return menuItem;
    }


    private Component createActualSizeMenuItem() {
        JMenuItem menuItem = new JMenuItem("还原");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().zoom().reset();
            }
        });
        return menuItem;
    }

    private Component createZoomOutMenuItem() {
        JMenuItem menuItem = new JMenuItem("缩小");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().zoom().out();
            }
        });
        return menuItem;
    }

    private Component createZoomInMenuItem() {
        JMenuItem menuItem = new JMenuItem("放大");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().zoom().in();
            }
        });
        return menuItem;
    }

    private Component createHTML5VideoMenuItem() {
        JMenuItem menuItem = new JMenuItem("直播测试");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("https://live.bilibili.com/");
            }
        });
        return menuItem;
    }

    private Component createEchartsMenuItem() {
        JMenuItem menuItem = new JMenuItem("Echarts演示");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("https://echarts.apache.org/examples/zh/index.html");
            }
        });
        return menuItem;
    }

    private Component createJavaScriptDialogsMenuItem() {
        JMenuItem menuItem = new JMenuItem("VUE支持");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("https://element.eleme.cn/#/zh-CN/component/switch");
            }
        });
        return menuItem;
    }

    private Component createDownloadFileMenuItem() {
        JMenuItem menuItem = new JMenuItem("下载文件测试");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("http://www.51xiazai.cn/soft/85579.htm");
            }
        });
        return menuItem;
    }

    public static class ViewCode implements ActionListener {

        private BrowserView browserView;

        public ViewCode(BrowserView browserView) {
            this.browserView = browserView;
        }

        public void actionPerformed(ActionEvent e) {
            String html = browserView.getBrowser().mainFrame().get().html();
            ViewSourceController.viewCode = html;
            String url = Solon.cfg().get("easy-borwser.server-url") + "/reviewCode.html";
            EasyBrowserApplication.insertTab(TabFactory.createTab(url,
            		browserView.getBrowser().engine().newBrowser()));
        }
    }


    private JMenuItem createConsoleMenuItem() {
        consoleMenuItem = new JMenuItem(RUN_JAVASCRIPT);
        consoleMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (RUN_JAVASCRIPT.equals(consoleMenuItem.getText())) {
                    consoleMenuItem.setText(CLOSE_JAVASCRIPT);
                    firePropertyChange("JSConsoleDisplayed", false, true);
                } else {
                    consoleMenuItem.setText(RUN_JAVASCRIPT);
                    firePropertyChange("JSConsoleClosed", false, true);
                }
            }
        });
        return consoleMenuItem;
    }

    private JMenuItem createUploadFileMenuItem() {
        JMenuItem menuItem = new JMenuItem("Upload File");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("http://www.cs.tut.fi/~jkorpela/forms/file.html#example");
            }
        });
        return menuItem;
    }

    private JMenuItem createPopupsMenuItem() {
        JMenuItem menuItem = new JMenuItem("Popup Windows");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("http://www.popuptest.com");
            }
        });
        return menuItem;
    }

    private JMenuItem createPDFViewerMenuItem() {
        JMenuItem menuItem = new JMenuItem("PDF预览");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                browserView.getBrowser().navigation().loadUrl("http://www.orimi.com/pdf-test.pdf");
            }
        });
        return menuItem;
    }


    private JMenuItem createAboutMenuItem() {
        JMenuItem menuItem = new JMenuItem("关于我们");
        menuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Frame parentFrame = (Frame) SwingUtilities.getWindowAncestor(ToolBar.this);
                AboutDialog aboutDialog = new AboutDialog(parentFrame);
                aboutDialog.setVisible(true);
            }
        });
        return menuItem;
    }

    private JMenuItem createLoginMenuItem() {
        JMenuItem menuItem;
        menuItem = new JMenuItem("登录/注销");
        menuItem.addActionListener(e -> {
//            LoginLogoutFrame loginLogoutFrame = new LoginLogoutFrame();
//            loginLogoutFrame.setVisible(true);
        });
        return menuItem;
    }

    private boolean isFocusRequired() {
        String url = addressBar.getText();
        return url.isEmpty() || url.equals(DEFAULT_URL);
    }

    @Override
    public void addNotify() {
        super.addNotify();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                if (isFocusRequired()) {
                    addressBar.requestFocus();
                    addressBar.selectAll();
                }
            }
        });
    }

    public static class ActionButton extends JButton {
        public ActionButton(String hint, Action action) {
            super(action);
            setContentAreaFilled(false);
            setBorder(BorderFactory.createEmptyBorder());
            setBorderPainted(false);
            setRolloverEnabled(true);
            setToolTipText(hint);
            setText(null);
            setFocusable(false);
            setDefaultCapable(false);
        }
    }

    private interface CheckBoxMenuItemCallback {
        void call(boolean selected);
    }

    public CollectBar getCollectBar() {
        return collectBar;
    }
}
